import random
import FCVector
import FCGenericCrowdEngine.Define as Define, kdtree, Util, Agent

reload(Define)
reload(kdtree)
reload(Util)
reload(Agent)

class Obstacle:
    def __init__( self ):
        self.mIdx = 0
        
        self.mNextObstacle = None
        self.mPrevObstacle = None
        	
        self.mPosition = FCVector.vector2D( 0.0, 0.0 )
        self.mNormal = FCVector.vector2D( 0.0, 0.0 )
        	
        self.mIsConvex = False
 
class Simulator:
    def __init__( self ):
        self.mAgentList = []
        self.mObstacleList = []

        self.mGlobalTime = 0.0
        self.mTimeStep = 0.0
        self.frameCount = 0
        
        self.mKdTree = kdtree.KdTree( self )
        
        #_left = Define.wall(FCVector.vector2D(-1280,1280),FCVector.vector2D(-1280,-1280))            
        #_right = Define.wall(FCVector.vector2D(1280,-1280),FCVector.vector2D(1280,1280))
        #_top = Define.wall(FCVector.vector2D(1280,1280),FCVector.vector2D(-1280,1280))          
        #_bottom = Define.wall(FCVector.vector2D(-1280,-1280),FCVector.vector2D(1280,-1280))
        #self.mWall = []
        #self.mWall.append(_left)
        #self.mWall.append(_right)
        #self.mWall.append(_top)
        #self.mWall.append(_bottom)
        
    def preferredVelocities( self ):
        for _agent in self.mAgentList:
            _agent.preferredVelocity()

    def fnDoStep( self, _Dt, _terrainCheck ):
        self.mTimeStep = _Dt
        self.mKdTree.fnBuildObstacleTree()
        self.mKdTree.fnBuildAgentTree()
        
        for _agent in self.mAgentList:
            _agent.fnComputeNeighbors()
            _agent.fnComputeNewVelocity()
            
        for _agent in self.mAgentList:
            _agent.fnUpdate( _Dt, self.frameCount, _terrainCheck )

        self.mGlobalTime += _Dt

    def fnAddAgent( self, _x, _z, _radius, _isLod = False, _quality = 'middle' ):
        _agent = Agent.Agent( self, FCVector.vector2D(_x, _z), _radius, _isLod, _quality )
        _agent.mIdx = len( self.mAgentList )

        self.mAgentList.append( _agent )
        
        return _agent
        
    def fnAddObstacle( self, _Position, _Radius ):
        _Vertices = []
        _Vertices.append(FCVector.vector2D(_Position.x-_Radius,_Position.y-_Radius))
        _Vertices.append(FCVector.vector2D(_Position.x+_Radius,_Position.y-_Radius))
        _Vertices.append(FCVector.vector2D(_Position.x+_Radius,_Position.y+_Radius))
        _Vertices.append(FCVector.vector2D(_Position.x-_Radius,_Position.y+_Radius))
        
        if 2 > len( _Vertices ):
            return -1
            
        _ObstCnt = len( self.mObstacleList )
        for _Idx in range( 0, len(_Vertices) ):
            _Obstacle = Obstacle()
            _Obstacle.mPosition = _Vertices[_Idx]
            if 0 != _Idx:
                _Obstacle.mPrevObstacle = self.mObstacleList[len(self.mObstacleList) - 1]
                _Obstacle.mPrevObstacle.mNextObstacle = _Obstacle

            if _Idx == len(_Vertices) - 1:
                _Obstacle.mNextObstacle =  vrfself.mObstacleList[_ObstCnt]
                _Obstacle.mNextObstacle.mPrevObstacle = _Obstacle

            _TempIdx = 0
            if _Idx != len(_Vertices) - 1:
                _TempIdx = _Idx + 1

            _Obstacle.mNormal = _Vertices[_TempIdx] - _Vertices[_Idx]
            _Obstacle.mNormal.normalize()

            if 2 == len(_Vertices):
                _Obstacle.mIsConvex = True
            else:
                _PrevIdx = _Idx - 1
                if _Idx == 0: _PrevIdx = len(_Vertices) - 1
                
                _NextIdx = _Idx + 1
                if _Idx == len(_Vertices) - 1: _NextIdx = 0
                
                if 0 <= transform.leftof( _Vertices[_PrevIdx], _Vertices[_Idx], _Vertices[_NextIdx] ):
                    _Obstacle.mIsConvex = True
                else:
                    _Obstacle.mIsConvex = False
                    
            _Obstacle.mIdx = len(self.mObstacleList)
            
            self.mObstacleList.append(_Obstacle)
            
        return _ObstCnt